from sys import argv
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *


class MyPyOpenGLTest:
    def __init__(self, width=640, height=480, title=' PyOpenGL_运动模糊'):
        glutInit(len(argv), argv)
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
        glutInitWindowSize(width, height)
        glutInitWindowPosition(350, 200)
        self.window = glutCreateWindow(title.encode('gbk'))
        glutDisplayFunc(self.draw)
        glutReshapeFunc(self.reshape)
        glutKeyboardFunc(self.ascii_key)
        glClearColor(0.6, 0.6, 0.6, 1)
        # 启用深度测试
        glEnable(GL_DEPTH_TEST)
        # 使用光照，设置光源属性
        glLightfv(GL_LIGHT0, GL_POSITION, (-2, 0, -1, 1))
        glLightfv(GL_LIGHT0, GL_SPECULAR, (1, 1, 1, 1))
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        # 设置物体表面材质对环境光、漫反射、镜面反射光的反应以及反光系数
        glMaterialfv(GL_FRONT, GL_AMBIENT, (1, 1, 1))
        glMaterialfv(GL_FRONT, GL_DIFFUSE, (1, 0.2, 0.3))
        glMaterialfv(GL_FRONT, GL_SPECULAR, (0.71, 0.6, 0.73))
        # 反光系数的取值范围为[0,128]
        glMaterialfv(GL_FRONT, GL_SHININESS, 100)
        # 球的初始位置x坐标
        self.x_sphere = -1.4
        # t是否处于发射状态
        self.shooting = False

    def reshape(self, w, h):
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glViewport(0, 0, w, h)
        aspect = w / h
        n = 1.5
        if w <= h:
            # 使用正交投影
            glOrtho(-n, n, -n/aspect, n/aspect, -5, 5)
        else:
            glOrtho(-n*aspect, n*aspect, -n, n, -5, 5)
        glMatrixMode(GL_MODELVIEW)

    def shoot(self, value):
        if self.x_sphere < 1.4:
            self.x_sphere = self.x_sphere + 0.1
            # 时间间隔越来越大，球的运动越来越慢
            glutTimerFunc(50+value, self.shoot, value+10)
        else:
            # 停止运动
            self.shooting = False
        glutPostRedisplay()

    def ascii_key(self, key, x, y):
        if key == b' ':
            # 按下空格键发射
            self.shooting = True
            glutTimerFunc(50, self.shoot, 1)
        # 按下字母r键恢复场景
        elif key == b'r':
            self.x_sphere = -1.4
            self.shooting = False
            glutPostRedisplay()
        else:
            return

    def draw(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glTranslate(self.x_sphere, 0.5, -2.5)

        alpha = 0.6
        n = 10
        for i in range(n):
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
            glColor3f(1, 0, 0)
            if self.shooting:
                # 处于发射状态时显示拖影，否则10个球完全重叠不显示拖影
                glTranslate(-0.015, 0, 0)
            # 绘制静止或运动的球
            glutSolidSphere(0.1, 20, 20)
            if i == 0:
                # 初始图形，跑在最前面的物体实影
                pass
                glAccum(GL_LOAD, alpha)
            else:
                # 叠加球后面跟随的拖影
                pass
                glAccum(GL_ACCUM, (1-alpha)/n)
        # 返回累积缓冲区中的图形，写入颜色缓冲区
        glAccum(GL_RETURN, 1)
        glLoadIdentity()
        glTranslate(0, -0.5, -2.5)
        # t绘制一个茶壶作为参照物
        glutSolidTeapot(0.3)
        glutSwapBuffers()

    # 消息主循环
    def mainloop(self):
        glutMainLoop()


if __name__ == '__main__':
    MyPyOpenGLTest().mainloop()
